package fhjoanneum.itm11.antesk.simplehack;
import java.util.*;

public class Handler
{
	private static Handler instance;
	
	// Members -----------------------------------------------------------
	private Scanner input = new Scanner(System.in);
	private Map map = new Map();
	private PlayerCharacter player;
	private String prompt = "What now? ";
	private String input_string; // temporary string
	private String last_command; // required for playerPosition()
	
	// Constructor -------------------------------------------------------
	private Handler(){}
	
	public static void createNewInstance(){
		instance = null;
	}
	
	
	// Methods ===========================================================
	public synchronized static Handler getInstance()
  {
		if (instance == null) 
    {
      instance = new Handler();
    }
    
		return instance;
  }
	
	// Getters and setters -----------------------------------------------
	public Map getMap(){return map;}
	public String getInput_string(){return input_string;}
	public void setInput_string(String input_string){
  	this.input_string = input_string;}


	// Position index of PlayerCharacter
	public int playerPosition()
	{
		if(getDirection(last_command) == Direction.EXIT)
		{
			return map.getTiles().indexOf( player.getPosition() );
		}
		else
		{
			return playerPosition(getDirection(last_command));
		}
	}
	
	// Position of other character
	public int playerPosition(Direction direction)
	{
		Tile character_position = 
				player.getPosition().getNeighbor(direction);
		
		if(character_position.getCharacter() != null) // character on tile
		{
			return map.getTiles().indexOf(character_position);
		}
		else
		{
			return -1;
		}
	}
	
	// Initialization of player character
	public void playerInit()
	{
		player = (PlayerCharacter) map.getPlayerCharacter().getPosition().
				getCharacter();
	}

	// Command loop for user input. Possible inputs:
	public void inputLoop()
	{		
		while(true)
		{
			try
      {
	      System.out.print(prompt);
	      String user_input = input.nextLine();
	      last_command = user_input;
	      
	      // Exit command
	      if(user_input.equals("quit") || 
	      		user_input.equals("exit"))
	      {
	      	System.out.println("Godbye!");
	      	break;
	      }
	      // Use command
	      else if(user_input.startsWith("use") )
	      {
	      	use(getInt(user_input));
	      }
	      // List inventory command
	      else if(user_input.equals("inventory"))
	      {
	      	player.getInventory().listInventory(player);
	      }
	      // Map command
	      else if(user_input.equals("map"))
	      {
	      	map.printMap();
	      }
	      // Open command
	      else if(user_input.startsWith("open") )
	      {
	      	open(getDirection(user_input));
	      }
	      // Move command
	      else if(user_input.startsWith("move") )
	      {
	      	move(getDirection(user_input));
	      }
	      // Show stats command
	      else if(user_input.equals("stats"))
	      {
	      	player.showStats();
	      }
	      // DEBUG COMMANDS * BEGIN ======================================
	      else if(user_input.equals("kill"))
	      {
	      	player.setHitpoints(0);
	      	System.out.println(player.getName() + 
	      			" has committed suicide.");
	      }
	      else if(user_input.equals("heal"))
	      {
	      	player.changeHitpoints(50);
	      	System.out.println(player.getName() + 
	      			" has been healed for 50 HP.");
	      }
	      // Show stats command with direction
	      else if(user_input.startsWith("stats") )
	      {
	      	try
	        {
	          System.out.println("Stats of " + player.getPosition().
	          		getNeighbor(getDirection(user_input)).getCharacter().
	          		getName());
	          
	          map.getTiles().
	          	elementAt(playerPosition(getDirection(user_input))).
	          	getCharacter().showStats();
	        }
	        catch (Exception e)
	        {
	          System.out.println("Nothing at this position");
	        }
	      }
	      // DEBUG COMMANDS * END ========================================
	      // Attack command
	      else if(user_input.startsWith("attack") )
	      {
	      	attack(getDirection(user_input));
	      }
	      
	      // Check if the player is still alive
	      if(player.getHitpoints() <= 0)
	      {
	      	System.out.println(player.getName() + "'s " +
	      			"body lies forgotten in the darkness of the cave, cov" +
	      			"ered in blood and urin.\nGAME OVER!");
	      	break;
	      }
      }
      catch (Exception e)
      {
	      System.out.println("Error: unknown command ");
	      e.printStackTrace();
      }
		}
		
	}

	// Greeting message --------------------------------------------------
	public void greeting()
	{
		System.out.println("SimpleHack 0.3");
	}
	
	// Name entering -----------------------------------------------------
	public void enterHeroName()
	{
		System.out.println("Enter your name, Hero...");
		
		String newname = input.nextLine();
		
		if(!newname.isEmpty())
		{
			player.setName(newname);
		}
				
		System.out.println(player.getName() + 
				"! You find yourself in a grim dark dungen!");
	}
	
	// Getter for Direction of movement, attack, open and other methods --
	/// returns the Direction that matches the first capital character
	/// after a ' ' (space) character.
	public Direction getDirection(String string)
	{	
		if(string.indexOf(' ') > -1)
		{
			input_string = string.substring(string.indexOf(' ') + 1);
			
			if(input_string.length() == 1)
			{
				if(input_string.compareTo("N") == 0)
				{
					return Direction.NORTH;
				}
				else if(input_string.compareTo("S") == 0)
				{
					return Direction.SOUTH;
				}
				else if(input_string.compareTo("W") == 0)
				{
					return Direction.WEST;
				}
				else if(input_string.compareTo("E") == 0)
				{
					return Direction.EAST;
				}
				else
				{
					return Direction.EXIT;
				}
			}
		}
		
		return Direction.EXIT;
	}
	
	// getInteger
	public int getInt(String string)
	{	
		if(string.indexOf(' ') > -1)
		{
			input_string = string.substring(string.indexOf(' ') + 1);
				
			try
      {
	      return Integer.parseInt(input_string);
      }
      catch (NumberFormatException e)
      {
      	// System.out.println("Please enter a number.");
	      return -1;
      }
		}
		else
		{
			return -1;
		}
	}
	
	// Move method for exception handling --------------------------------
	public void move(Direction direction)
	{
		if(direction == Direction.EXIT)
		{
			System.out.println("Usage: move [N,E,S,W]");
		}
		else
		{
			player.move(direction);
			map.printMap();
		}
	}
	
	// Attack method for exception handling ------------------------------
	public void attack(Direction direction)
	{
		if(direction == Direction.EXIT)
		{
			System.out.println("Usage: move [N,E,S,W]");
		}
		else
		{
			player.attack(direction);
			
			if(player.getPosition().getNeighbor(direction).getCharacter() != null)
			{
				switch(direction)
				{
				case NORTH:
					player.getPosition().getNeighbor(direction).getCharacter().
					attack(Direction.SOUTH);
					break;
				case SOUTH:
					player.getPosition().getNeighbor(direction).getCharacter().
					attack(Direction.NORTH);
					break;
				case EAST:
					player.getPosition().getNeighbor(direction).getCharacter().
					attack(Direction.WEST);
					break;
				case WEST:
					player.getPosition().getNeighbor(direction).getCharacter().
					attack(Direction.EAST);
					break;
				case EXIT:
					break;
				}
			}
		}
	}
	
	// Stats method for exception handling -------------------------------
	public void stats(Direction direction)
	{
		if(direction == Direction.EXIT)
		{
			System.out.println("Usage: stats [N,E,S,W]");
		}
		else
		{
			player.showStats();
		}
	}
	
	// Open method for exception handling --------------------------------
	public void open(Direction direction)
	{
		if(direction == Direction.EXIT)
		{
			System.out.println("Usage: open [N,E,S,W]");
		}
		else
		{
			player.open(direction);
		}
	}
	
	// Use method for exception handling ---------------------------------
	public void use(int index)
	{
			player.use(index);
	}
}
